﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Events {

	public interface IEvent
    {
        int getInt();
        bool getBool();
        float getFloat();
        double getDouble();
        string getString();
        Vector2 getVec2();
        Vector3 getVec3();
        GameObject getGameObject();
        Transform getTransform();
        object getObject();

        EventDelegate getDelegate();

        System.Action getAction();
    }

    public class AbstractEvent : IEvent
    {
        virtual public int getInt()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return 0;
        }

        virtual public bool getBool()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return true;
        }

        virtual public float getFloat()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return 0;
        }

        virtual public double getDouble()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return 0;
        }

        virtual public string getString()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return "";
        }
        virtual public Vector2 getVec2()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return Vector2.zero;
        }
        virtual public Vector3 getVec3()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return Vector3.zero;
        }
        virtual public GameObject getGameObject()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return null;
        }
        virtual public Transform getTransform()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return null;
        }
        virtual public object getObject()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return null;
        }

        virtual public EventDelegate getDelegate()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return null;
        }

        virtual public System.Action getAction()
        {
            Debugger.LogError("you must override this function if you want to use it");

            return null;
        }
    }

	public static M Create<M, T>(T v) where M : AbstractEvent, new()
    {
        return new M();
    }

	public class Event<T> : AbstractEvent
    {
        protected T _t;
		public Event(T t)
        {
            _t = t;
        }
    }


    public class Event_int : Event<int>
    {
		public Event_int(int t) : base(t)
        {
        }
        public override int getInt()
        {
            return _t;
        }
    }

    public class Event_bool : Event<bool>
    {
        public Event_bool(bool b) : base(b)
        {
           
        }

        public override bool getBool()
        {
            return _t;
        }
    }

    public class Event_float : Event<float>
    {
        public Event_float(float f) : base(f)
        {
        }

        public override float getFloat()
        {
            return _t;
        }
    }

    public class Event_double : Event<double>
    {
        public Event_double(double d) : base(d)
        {
        }

        public override double getDouble()
        {
            return _t;
        }
    }

    public class Event_string : Event<string>
    {
        public Event_string(string str):base(str)
        {
        }

        public override string getString()
        {
            return _t;
        }
    }

    public class Event_GameObject : Event<GameObject> 
    {
        public Event_GameObject(GameObject o) : base(o)
        {
        }

        public override GameObject getGameObject()
        {
            return _t;
        }
    }

    public class Event_Transform : Event<Transform> 
    {
        public Event_Transform(Transform t) : base(t)
        {
        }

        public override Transform getTransform()
        {
            return _t;
        }
    }

    public class Event_Vector2 :  Event<Vector2>
    {
        public Event_Vector2(Vector2 v) : base(v)
        {
        }

        public override Vector2 getVec2()
        {
            return _t;
        }
    }

    public class Event_Vector3 : Event<Vector3> 
    {
        public Event_Vector3(Vector3 v) : base(v)
        {
        }

        public override Vector3 getVec3()
        {
            return _t;
        }
    }

    public class Event_object : Event<object>
    {
        public Event_object(object o) : base(o)
        {
        }

        public override object getObject()
        {
            return _t;
        }
    }

    public class Event_Delegate : Event<EventDelegate>
    {
        public Event_Delegate(EventDelegate o) : base(o)
        {
        }

        public override EventDelegate getDelegate()
        {
            return _t;
        }
    }

    public class Event_Action : Event<System.Action>
    {
        public Event_Action(System.Action o)
            : base(o)
        {
        }

        public override System.Action getAction()
        {
            return _t;
        }
    }

    public delegate void Listener(IEvent e);

	public static Dispatcher createDispather()
    {
        return new Dispatcher();
    }

	public static IEvent create(int e)
    {
        return new Event_int(e);
    }

    public static IEvent create(float e)
    {
        return new Event_float(e);
    }

    public static IEvent create(double e)
    {
        return new Event_double(e);
    }

    public static IEvent create(bool e)
    {
        return new Event_bool(e);
    }

    public static IEvent create(string e)
    {
        return new Event_string(e);
    }

    public static IEvent create(GameObject e)
    {
        return new Event_GameObject(e);
    }

    public static IEvent create(Transform e)
    {
        return new Event_Transform(e);
    }

    public static IEvent create(Vector2 e)
    {
        return new Event_Vector2(e);
    }

    public static IEvent create(Vector3 e)
    {
        return new Event_Vector3(e);
    }

    public static IEvent create(object e)
    {
        //Debugger.Log(e);
        return new Event_object(e);
    }

    public static IEvent create(EventDelegate del)
    {
        return new Event_Delegate(del);
    }

    public static IEvent create(System.Action del)
    {
        return new Event_Action(del);
    }

	public class DispatcherT<T>
    {
        Dictionary<T, Listener> dic_Cbs = new Dictionary<T, Listener>();

        public DispatcherT()
        {

        }

        public void registEvent(T eve, Listener cb)
        {
            if (!dic_Cbs.ContainsKey(eve))
                dic_Cbs.Add(eve, cb);
            else
                dic_Cbs[eve] += cb;
        }

        public void dispatchEvent(T eve, IEvent e = null)
        {
            if (dic_Cbs.ContainsKey(eve))
                dic_Cbs[eve](e);
        }

        public void removeEvent(T eve, Listener cb)
        {
            if (dic_Cbs.ContainsKey(eve))
            {
                dic_Cbs[eve] -= cb;
                if (null == dic_Cbs[eve])
                    dic_Cbs.Remove(eve);
            }
        }

        public int Count
        {
            get
            {
                return dic_Cbs.Count;
            }
        }
    }

    public class Dispatcher : DispatcherT<string>
    {

    }
}
